package com.wry.file.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.RenderData;
import com.deepoove.poi.data.TextRenderData;
import com.deepoove.poi.data.style.Style;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.deepoove.poi.policy.DynamicTableRenderPolicy;
import com.deepoove.poi.util.PoitlIOUtils;
import com.wry.file.utils.WordTableUtil;
//import jakarta.xml.bind.JAXBElement;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.poi.xwpf.usermodel.*;
//import org.docx4j.openpackaging.exceptions.Docx4JException;
//import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
//import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
//import org.docx4j.wml.Text;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <h1>  <h1>
 *
 * @author wry
 * @since 2024/9/5 9:29
 */
@RequestMapping("file")
@RestController
public class WordController {

    /**
     * docx4j
     */
    @PostMapping("word-test01")
    public void wordTest01(@RequestParam("file") MultipartFile file, HttpServletResponse response) throws Exception {
//        try {
//            final InputStream inputStream = file.getInputStream();
//            final WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(inputStream);
//            Map<String,String> placeholdersMap = new HashMap<>();
//            placeholdersMap.put(" (var1)", "这是var1的值");
//            placeholdersMap.put(" (var2)", "这是var2的值");
//            replacePlaceholders(wordMLPackage, placeholdersMap);
//            // 文档写入字节数组输出流
//            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//            wordMLPackage.save(byteArrayOutputStream);
//            response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
//            response.setHeader("Content-Disposition", "attachment; filename=test-new.docx");
//            response.setContentLength(byteArrayOutputStream.size());
//            response.getOutputStream().write(byteArrayOutputStream.toByteArray());
//            response.getOutputStream().flush();
//        }catch (Exception e) {
//
//        }
    }

//    private void replacePlaceholders(WordprocessingMLPackage wordMLPackage, Map<String, String> placeholdersMap) throws Exception{
//        // 获取文档所有的文本内容
//        List<Object> texts = wordMLPackage.getMainDocumentPart().getJAXBNodesViaXPath("//w:t", true);
//        for (Object obj : texts) {
//            JAXBElement<?> element = (JAXBElement<?>) obj;
//            if (element.getValue() instanceof Text) {
//                Text text = (Text) element.getValue();
//                // 文本值
//                final String textValue = text.getValue();
//                if (placeholdersMap.containsKey(textValue)) {
//                    // 此文本值是占位符
//                    final String value = placeholdersMap.get(textValue);
//                    text.setValue(value);
//                }
//            }
//        }
//    }

//    private void read1(InputStream inputStream) throws Exception{
//        WordprocessingMLPackage wordprocessingMLPackage = WordprocessingMLPackage.load(inputStream);
//        // 获取文档的主要部分
//        final MainDocumentPart documentPart = wordprocessingMLPackage.getMainDocumentPart();
//        // 提取文本内容
//        final String documentText  = documentPart.getXML();
//
//        for (Object o : documentPart.getContent()) {
//            if (o instanceof  org.docx4j.wml.P) {
//                org.docx4j.wml.P p = (org.docx4j.wml.P) o;
//                for (Object o1 : p.getContent()) {
//
//                }
//            }
//        }
//    }

    /**
     * poi-tl
     * 导入一个模板，实现数据填充、循环表格、单元格合并
     *
     */
    @PostMapping("word-test02")
    public void wordTest02(@RequestParam("file") MultipartFile file, HttpServletResponse response) throws Exception {
//        templateDemo(file, response);
        tableDemo01(file, response);
    }

    private void templateDemo(MultipartFile file, HttpServletResponse response) throws Exception{
        final XWPFTemplate template = XWPFTemplate.compile(file.getInputStream()).render(
                new HashMap<String, Object>() {{
                    put("title", "Hi, poi-tl Word模板引擎");
                }}
        );
        response.setContentType("application/octet-stream");
        response.setHeader("Content-disposition","attachment;filename=\""+"out_template.docx"+"\"");
        final OutputStream ops = response.getOutputStream();
        final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(ops);
        template.write(bufferedOutputStream);
        bufferedOutputStream.flush();
        ops.flush();
        PoitlIOUtils.closeQuietlyMulti(template, bufferedOutputStream, ops);
    }

    private void tableDemo01(MultipartFile file, HttpServletResponse response) throws Exception {
        List<GoodsInfo> goodsInfoList = new ArrayList<>();
        for (int i = 1; i <= 50; i++) {
            GoodsInfo goodsInfo = new GoodsInfo();
            goodsInfo.setNo(i);
            goodsInfo.setCnName("中文"+i);
            goodsInfo.setEnName("english"+i);
            goodsInfo.setGoal("目的"+i);
            goodsInfo.setInNo(i);
            goodsInfo.setRemark("备注"+i);
            goodsInfoList.add(goodsInfo);
        }
        GoodsInfo goodsInfo1 = new GoodsInfo();
        goodsInfo1.setNo(1);
        goodsInfo1.setCnName("中文"+1);
        goodsInfo1.setEnName("english"+1);
        goodsInfo1.setGoal("目的"+1);
        goodsInfo1.setInNo(1);
        goodsInfo1.setRemark("备注"+1);
        goodsInfoList.add(goodsInfo1);

        GoodsInfo goodsInfo = new GoodsInfo();
        goodsInfo.setNo(3);
        goodsInfo.setCnName("中文"+3);
        goodsInfo.setEnName("english"+3);
        goodsInfo.setGoal("目的"+3);
        goodsInfo.setInNo(3);
        goodsInfo.setRemark("备注"+3);

        GoodsInfo goodsInfo2 = new GoodsInfo();
        goodsInfo2.setNo(5);
        goodsInfo2.setCnName("中文"+5);
        goodsInfo2.setEnName("english"+5);
        goodsInfo2.setGoal("目的"+5);
        goodsInfo2.setInNo(5);
        goodsInfo2.setRemark("备注"+5);
        goodsInfoList.add(goodsInfo);
        goodsInfoList.add(goodsInfo2);

        GoodsInfo goodsInfo99 = new GoodsInfo();
        goodsInfo99.setNo(99);
        goodsInfo99.setCnName("中文"+99);
        goodsInfo99.setEnName("english"+99);
        goodsInfo99.setGoal("目的"+99);
        goodsInfo99.setInNo(99);
        goodsInfo99.setRemark("备注"+99);
        goodsInfoList.add(goodsInfo);
        goodsInfoList.add(goodsInfo2);
        goodsInfoList.add(goodsInfo99);

        List<Ingredient> ingredientList = new ArrayList<>();
        for (int i = 1; i <= 15; i++) {
            Ingredient ingredient = new Ingredient();
            ingredient.setNo(i);
            ingredient.setCnName("中文名称"+i);
            ingredient.setContent("90."+i);
            ingredient.setRequire("《化妆品安全技术规范》要求"+i);
            ingredient.setConclusion("权威机构评估结论"+i);
            ingredient.setDosage("8"+i+"%");
            ingredient.setMaxDosage("9"+i+"%");
            ingredient.setFinalConclusion("评估结论"+i);
            ingredient.setDoc(String.valueOf(i));
            ingredientList.add(ingredient);
        }

        // 创建样式：宋体，四号字
        Style textStyle = new Style();
        // 四号字 14
        textStyle.setFontSize(14);
        textStyle.setFontFamily("宋体");
        StringBuilder wenxContent = new StringBuilder();
        for (WenX wenx : list) {
            // 四个空格来模拟首行缩进两个字符
            wenxContent
                    .append(wenx.getNo())
                    .append(".")
                    .append(wenx.getDesc())
                    .append("\n");
        }
        // 将文献内容封装为TextRenderData，并设置样式
        RenderData wenxRenderData = new TextRenderData(wenxContent.toString(), textStyle);

        // 排序一下
        final List<GoodsInfo> sortList = goodsInfoList.stream().sorted(Comparator.comparing(GoodsInfo::getNo)).collect(Collectors.toList());

        LoopRowTableRenderPolicy loopRowTableRenderPolicy = new LoopRowTableRenderPolicy();
        final Configure config = Configure.builder()
                .bind("goods", new WordTableUtil.TableMergePolicy01())
                .bind("ingredient", new LoopRowTableRenderPolicy())
                .build();

        XWPFTemplate template = XWPFTemplate.compile(file.getInputStream(), config).render(
                new HashMap<String, Object>() {{
                    put("goods", sortList);
                    put("ingredient", ingredientList);
                    put("wenxList",wenxRenderData);
                }}
        );
        response.setContentType("application/octet-stream");
        response.setHeader("Content-disposition","attachment;filename=\""+"goods_template.docx"+"\"");
        final OutputStream ops = response.getOutputStream();
        final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(ops);
        template.write(bufferedOutputStream);
        bufferedOutputStream.flush();
        ops.flush();
        PoitlIOUtils.closeQuietlyMulti(template, bufferedOutputStream, ops);
    }

    @Data
    public static class GoodsInfo{
        private Integer no;
        private String cnName;
        private String enName;
        private String goal;
        private Integer inNo;
        private String remark;
    }

    @Data
    public static class Ingredient {
        private Integer no;
        private String cnName;

        private String content;

        private String require;

        private String conclusion;

        private String dosage;

        private String maxDosage;

        private String finalConclusion;

        private String doc;
    }

    @Data
    @AllArgsConstructor
    public static class WenX {
        private Integer no;

        private String desc;
    }

    static List<WenX> list = List.of(
            new WenX(1,"测试的-国家食品药品监督管理总局，关于发布化妆品安全技术规范（2015年版）的公告，2015年第268号"),
            new WenX(2, "测试的-国家药品监督管理局，关于发布《已使用化妆品原料目录（2021年版）》的公告，2021年第62号"),
            new WenX(3, "The SCCS Notes of Guidance for the Testing of Cosmetic Ingredients and their Safety Evaluation(12th Revision).available from SCCS"),
            new WenX(4, "国家食品药品监督管理总局，关于印发化妆品用乙醇等3种原料要求的通知，2011年第500号"),
            new WenX(5, "日本《药事法》厚生劳动省第331号公告《化妆品质量标准附录3》"),
            new WenX(6, "Safety Assessment of Cyclomethicone, Cyclotetrasiloxane, Cycl-opentasiloxane, Cyclohexasiloxane, and Cycloheptasiloxane. available from CIR")
            ,new WenX(7, "Final Report of the Safety Assessmentof Niacinamide and Niacin from CIR.International Journal of Toxicology, 24(Suppl.5):1-31,2005")
    );


    /**
     * 字段对应表格中的索引位置
     */
    static Map<String,Integer> FiledMap = Map.of(
            "no",0,
            "cnName",1,
            "enName",2,
            "goal",3,
            "inNo",4,
            "remark",5
    );



    public static class DetailTablePolicy extends DynamicTableRenderPolicy  {

        @Override
        public void render(XWPFTable table, Object data) throws Exception {
            if (data == null) {
                return;
            }
            List<GoodsInfo> goodsInfoList = (List<GoodsInfo>) data;
            if (CollectionUtil.isEmpty(goodsInfoList)) {
                return;
            }
            // 起始索引
            int index = 0;
            for (int i = 0; i < goodsInfoList.size(); i++) {
                // 当前行数据
                final GoodsInfo goodsInfo = goodsInfoList.get(i);
                // 从第二个数据开始比较
                if (i > 0) {
                    final GoodsInfo beforeGoodsInfo = goodsInfoList.get(index);
                    final boolean equals = goodsInfo.getNo().equals(beforeGoodsInfo.getNo());
                    if (equals) {
                        // merge
                    }
                }
                final XWPFTableRow row = table.createRow();
                row.getCell(FiledMap.get("no")).setText(goodsInfo.getNo().toString());
                row.getCell(FiledMap.get("cnName")).setText(goodsInfo.getCnName());
                row.getCell(FiledMap.get("enName")).setText(goodsInfo.getEnName());
                row.getCell(FiledMap.get("goal")).setText(goodsInfo.getGoal());
                row.getCell(FiledMap.get("inNo")).setText(goodsInfo.getInNo().toString());
                row.getCell(FiledMap.get("remark")).setText(goodsInfo.getRemark());
                index++;
            }
        }
    }
}
